<template>
  <div :class="[chartClass, 'components-chart-box', props.bordered && 'bordered']" v-loading="loading"
    :style="{ height, width }">
    <div class='chart-container'>
      <h4 v-if="props.title" class="chart-title">{{ props.title }}</h4>
      <div class="chart" ref="chartRef">
      </div>
    </div>
    <div class="legend-box" v-if="colorChartData.length > 0">
      <ul class="legend-list" ref="scrollContent">
        <li v-for="(item, index) in colorChartData" :key="index" @mouseover="hoverSeries(item.name)"
          @mouseleave="hoverCancel(item.name)" @click="toggleSeries(item.name)">
          <span class="legend"
            :style="{ background: `linear-gradient(90deg, ${item.show ? item.colorArr[0] : '#ccc'}, ${item.show ? item.colorArr[1] : '#ccc'})` }"></span>
          <div class="value-box">
            <span>{{ item.name }}：</span>
            <span class="value">{{ item.value }}</span>
          </div>
        </li>
      </ul>
      <div v-if="showPage" class="op-box">
        <a-button type="link" :icon="h(CaretUpOutlined)" @click="scroll(-1)" :disabled="currentPage === 1"></a-button>
        {{ currentPage }}/{{ totalPages }}
        <a-button type="link" :icon="h(CaretDownOutlined)" @click="scroll(1)"
          :disabled="currentPage === totalPages"></a-button>
      </div>
    </div>
  </div>
</template>
<script lang="ts"
  setup>
  import { onMounted, PropType, Ref, ref, watch, onUnmounted, h, nextTick } from 'vue'
  import { useECharts } from '@/hooks/web/useECharts'
  import { EChartsOption } from 'echarts'
  import { getRandomColor, lightenColor } from '../common'
  import { pieColorArr } from './data'
  import { YData } from '@/api/common/model/chart'
  import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons-vue'
  import '../style.scss'

  const props = defineProps({
    width: {
      type: String as PropType<string>,
      default: '100%',
    },
    height: {
      type: String as PropType<string>,
      default: '100%',
    },
    loading: {
      type: Boolean,
      default: false,
    },
    bordered: {
      type: Boolean,
      default: true,
    },
    title: {
      type: String as PropType<string>,
      default: '',
    },
    chartData: {
      type: Array as PropType<YData[]>,
      default: () => [],
    },
    chartClass: {
      type: Object as PropType<string>,
    },
  })

  interface ColorData extends YData {
    colorArr: string[]
  }

  let resizeObserver: ResizeObserver | null = null
  const chartRef = ref<HTMLDivElement | null>(null)
  const scrollContent = ref<HTMLElement | null>(null)
  const showPage = ref(false)
  const itemHeight = 18
  const colorChartData = ref<ColorData[]>([])
  const chartWidth = ref(0)
  const chartHeight = ref(0)
  const itemsPerPage = ref(0) // 每页显示的图例数量
  const totalPages = ref(0) // 总页数
  const currentPage = ref(1) // 当前页码
  const { setOptions, echarts, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>)

 // 刻度
  const bgGaugeR = 90
  const gap = 0.5
  // 外层圆
  const bgBigPieR = [bgGaugeR - 15 - gap, bgGaugeR - 15]
  // 数据圆
  const pieR = [bgBigPieR[0]/2, bgBigPieR[0] - 1]
  // 内层圆
  const bgSmallPieR = [pieR[0] - 2, pieR[0] - 1]
  // 数据圆
  const pieC = ['50%', '50%']

  // 背景色
  const bgLineColor = 'rgba(36,108,249,0.2)'

  const pieBgOptions = [
    // 外环
    {
      type: 'pie',
      silent: true,
      radius: bgBigPieR.map(num => `${num}%`), //图表尺寸
      center: pieC,
      animation: false,
      emptyCircleStyle: {
        color: bgLineColor,
      },
    },
    // 内环
    {
      type: 'pie',
      silent: true,
      radius: bgSmallPieR.map(num => `${num}%`), //图表尺寸
      center: pieC,
      color: bgLineColor,
      animation: false,
      emptyCircleStyle: {
        color: bgLineColor,
      },
    },
    {
      type: 'gauge',
      splitNumber: 30, //刻度数量
      min: 0,
      max: 100,
      radius: `${bgGaugeR}%`, //图表尺寸
      center: pieC,
      startAngle: 0,
      endAngle: 360,
      axisLine: {
        lineStyle: {
          width: 1.5,
          shadowBlur: 0,
          color: [[1, bgLineColor]],
        },
      },
      axisTick: {
        show: true,
        lineStyle: {
          color: bgLineColor,
          width: 1,
        },
        length: '7%',
        distance: 2,
        splitNumber: 2,
      },
      splitLine: {
        show: false,
      },
      axisLabel: {
        show: false,
      },
      pointer: {
        show: false,
      },
      detail: {
        show: false,
      },
    },
  ]

  const setChartColor = () => {
    if (!Array.isArray(props.chartData)) return
    colorChartData.value = props.chartData.map((item, index) => {
      let colorArr = pieColorArr?.[index]
      if (!colorArr) {
        const color1 = getRandomColor()
        const color2 = lightenColor(color1)
        colorArr = [color1, color2]
      }
      return ({
        ...item, colorArr,
        show: true,
        label:{
            formatter: function (data) {
              return `${data.name} (${data.percent.toFixed(0)}%)`
            }
          }
      })
    })
  }

  const getChartOptions = () => {
    const chartData = colorChartData.value
    console.log(chartData, 'chartData')
    const option = {
      backgroundColor: '#fff',
      tooltip: {
        trigger: 'item',
      },
      legend: {
        show: false,
        type: 'scroll',
        orient: 'vertical',

      },
      series: [
        ...pieBgOptions,
        {
          type: 'pie',
          radius: pieR.map(num => `${num}%`),
          center: pieC,
          data: chartData,
          avoidLabelOverlap: true,
          itemStyle: {
            color: ({ data: { colorArr } }) => {
              return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: colorArr[1] },
                { offset: 1, color: colorArr[0] },
              ])
            },
          },
          labelLine: {
            show: true,
            showAbove: false,
            length: '10',
            // length2: '8%',
            smooth: true,
          },
          label: {
            show: true,
            position: 'outside',
            bleedMargin: 5,
            overflow: 'truncate',
          },
        },
      ],
    }
    return option as EChartsOption
  }

  onMounted(() => {
    resizeObserver = new ResizeObserver(() => {
      resize()
      getDomSize()
      calculatePagination()
    })
    if (chartRef.value) {
      resizeObserver.observe(chartRef.value as HTMLDivElement)
    }
  })

  onUnmounted(() => {
    if (resizeObserver && chartRef.value) {
      resizeObserver.unobserve(chartRef.value as HTMLDivElement)
    }
  })
  const hoverSeries = (name) => {
    getInstance()!.dispatchAction({
      type: 'highlight',
      // 可选，数据项名称，在有 dataIndex 的时候忽略
      name,
    })
  }
  const hoverCancel = (name) => {
    getInstance()!.dispatchAction({
      type: 'downplay',
      name,
    })
  }

  const toggleSeries = (name) => {
    getInstance()!.dispatchAction({
      type: 'legendToggleSelect',
      name,
    })
    const current = colorChartData.value.find(item => item.name === name)
    if (current)  {
      current.show = !current.show
    }
  }
  const getDomSize = () => {
    if (!chartRef.value) {
      return
    }
    chartWidth.value = chartRef.value.clientWidth
    chartHeight.value = chartRef.value.clientHeight
    setOptions(getChartOptions())
  }

  const calculatePagination = async () => {
    showPage.value = false
    currentPage.value = 1
    itemsPerPage.value = 0
    totalPages.value = 0
    if (scrollContent.value) {
      scrollContent.value.scrollTo({
        top: 0
      })
    }
    await nextTick()
    if (scrollContent.value) {
      const clientHeight = scrollContent.value.clientHeight
      const scrollHeight = scrollContent.value.scrollHeight
      if (scrollHeight > clientHeight) {
        showPage.value = true
        const num = Math.floor(clientHeight / itemHeight)
        itemsPerPage.value = num
        totalPages.value = Math.ceil(scrollHeight / (num * itemHeight))
      }

    }
  }

  const scroll = (direction) => {
    const scrollAmount = itemsPerPage.value * itemHeight
    currentPage.value += direction
    const top = direction * scrollAmount
    handleScroll(top)
  }

  const handleScroll = (top) => {
    if (scrollContent.value) {
      scrollContent.value.scrollBy({
        top,
        behavior: 'smooth'
      })
    }
  }

  const setData = () => {
    if (!props.chartData || !Array.isArray(props.chartData)) return
    const options = getChartOptions()
    setOptions(options)
  }

  watch(
    () => props.chartData,
    async (val) => {
      setChartColor()
      setData()
    },
    {
      immediate: true,
    },
  )

</script>
<style scoped
  lang="scss">
  .components-chart-box {
    display: flex;
    padding-top: 12px;

    .legend-box {
      display: flex;
      flex-direction: column;
      margin: 0 12px 12px 0;
      padding: 6px 12px;
      background: #F2F5F8;

      .legend-list {
        flex: 1;
        flex-shrink: 0;
        overflow: hidden;
        border-radius: 2px;


        li {
          display: flex;
          padding: 6px 0;
          color: var(--chart-text-color);
          font-size: 12px;
          line-height: 1;
          white-space: nowrap;
          cursor: pointer;

          .legend {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 2px;
          }

          .value-box {
            display: flex;
            flex: 1;
            justify-content: space-between;
            margin-left: 4px;

            .value {
              color: #333;
            }
          }
        }
      }

      .op-box {
        display: flex;
        align-items: center;
        justify-content: space-between;
        font-size: 12px;

        .ant-btn-link {
          color: #2f4554;
          font-size: 16px;

          &.is-disabled {
            color: #aaa;
          }
        }
      }
    }

    .chart-title {
      position: relative;
      top: 0;
      left: 0;
      flex: none;
      flex-shrink: 0;
      padding-left: 12px;

      &::before {
        left: 0;
      }
    }
  }

  .chart-container {
    display: flex;
    flex: 1;
    flex-direction: column;
    flex-shrink: 0;

    .chart {
      flex: 1;
      flex-shrink: 0;
      margin: 8px;
      overflow: hidden;
    }


  }
</style>
